package cn.portx.view;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.type.StringType;
import org.hibernate.type.TimestampType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import cn.portx.ICallback;
import cn.portx.entity.Billing;
import cn.portx.entity.BillingLog;
import cn.portx.entity.HexiaoLog;
import cn.portx.entity.OrderExpense;
import cn.portx.hibernate.HibernateDao;
import cn.portx.hibernate.ParseResult;

import com.bstek.bdf3.dorado.jpa.JpaUtil;
import com.bstek.bdf3.dorado.jpa.policy.SaveContext;
import com.bstek.bdf3.dorado.jpa.policy.impl.SmartSavePolicyAdapter;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.annotation.Expose;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.dorado.data.provider.Criteria;
import com.bstek.dorado.data.provider.Page;

@Component
public class AccountsReceivablePR {
	
	@Autowired
	private HibernateDao hibernateDao;
	
	@DataProvider
	@Transactional(readOnly = true)
	public void loadOrderExpense(Page<OrderExpense> page, Criteria criteria, Date hxrqStart, Date hxrqEnd) {
		List<String> oeId = null;
		if (null == hxrqStart && null == hxrqEnd) {
			
		}else {
			oeId = JpaUtil.linq(HexiaoLog.class,String.class)
					.select("orderExpenseId")
					.addIf(hxrqStart)
						.greaterThan("hxDate", hxrqStart)
					.endIf()
					.addIf(hxrqStart)
						.lessThan("hxDate", hxrqEnd)
					.endIf()
					.distinct()
					.list();
		}
		String ids  = "";
		if(null != oeId){
			for (int i = 0;i < oeId.size(); i++){
				if (i == oeId.size() - 1)
					ids += oeId.get(i);
				else
					ids += oeId.get(i) + ",";
			}
			
		}
		String sql = "SELECT\n" +
				"	*\n" +
				"FROM\n" +
				"	(\n" +
				"		SELECT\n" +
				"			oe.*, o.order_no_,\n" +
				"			o.voyage_,\n" +
				"			o.cnt_no_,\n" +
				"			o.cnt_no2_,\n" +
				"			o.bill_no_,\n" +
				"			o.box_type_,\n" +
				"			o.quantity_,\n" +
				"			o.finance_end_,\n" +
				"			o.zxrq_,\n" +
				"			o.order_date_,\n" +
				"			o.type_ AS order_type_,\n" +
				"			c.name_ AS customer_name_,\n" +
				"			v.name_ AS vessel_name_,\n" +
				"			ei.name_ AS expense_item_name_\n" +
				"		FROM\n" +
				"			t_order_expense oe\n" +
				"		INNER JOIN t_order o ON oe.order_id_ = o.id_\n" +
				"		LEFT JOIN t_customer c ON o.customer_id_ = c.id_\n" +
				"		LEFT JOIN t_vessel v ON o.vessel_id_ = v.id_\n" +
				"		LEFT JOIN t_expense_item ei ON oe.expense_item_id_ = ei.id_\n" +
				"		WHERE\n" +
				"			oe.type_ = '0' AND	o.target_id_ is null AND oe.expense_val_ > 0 " ;
		if("" != ids) {
		sql +=	"		AND oe.id_ in ( " + ids + ") \n";
		}
		sql += 	"		ORDER BY o.order_no_ ASC\n" +
				"		) t\n" +
				"		WHERE\n" +
				"		1 = 1";
		String countSql = "SELECT\n" +
				"	count(*)\n" +
				"FROM\n" +
				"	(\n" +
				"		SELECT\n" +
				"			oe.*, o.order_no_,\n" +
				"			o.voyage_,\n" +
				"			o.cnt_no_,\n" +
				"			o.cnt_no2_,\n" +
				"			o.bill_no_,\n" +
				"			o.box_type_,\n" +
				"			o.quantity_,\n" +
				"			o.finance_end_,\n" +
				"			o.zxrq_,\n" +
				"			o.order_date_,\n" +
				"			o.type_ AS order_type_,\n" +
				"			c.name_ AS customer_name_,\n" +
				"			v.name_ AS vessel_name_,\n" +
				"			ei.name_ AS expense_item_name_\n" +
				"		FROM\n" +
				"			t_order_expense oe\n" +
				"		INNER JOIN t_order o ON oe.order_id_ = o.id_\n" +
				"		LEFT JOIN t_customer c ON o.customer_id_ = c.id_\n" +
				"		LEFT JOIN t_vessel v ON o.vessel_id_ = v.id_\n" +
				"		LEFT JOIN t_expense_item ei ON oe.expense_item_id_ = ei.id_\n" +
				"		WHERE\n" +
				"			oe.type_ = '0' AND	o.target_id_ is null AND oe.expense_val_ > 0 ";
		if ("" != ids) {
		countSql +=	"		AND oe.id_ in ( " + ids + ") \n";
		}
		countSql += "		ORDER BY o.order_no_ ASC\n" +
				"		) t\n" +
				"		WHERE\n" +
				"		1 = 1";
		Map<String, Object> parametersMap = new HashMap<String, Object>();
		ParseResult result = this.hibernateDao.parseCriteria(criteria, true, "t");
		if (null != result) {
			sql += " and " + result.getAssemblySql();
			countSql += " and " + result.getAssemblySql();
			parametersMap.putAll(result.getValueMap());
		}
		Session session = hibernateDao.getSession(OrderExpense.class);
		this.hibernateDao.pagingSQLQuery(page, sql, countSql, parametersMap, new ICallback<Void, SQLQuery>() {

			@Override
			public Void execute(SQLQuery query) {
				query.addEntity("oe", OrderExpense.class).addScalar("order_no_", StringType.INSTANCE)
				.addScalar("voyage_", StringType.INSTANCE).addScalar("cnt_no_", StringType.INSTANCE)
				.addScalar("cnt_no2_", StringType.INSTANCE).addScalar("bill_no_", StringType.INSTANCE)
				.addScalar("box_type_", StringType.INSTANCE).addScalar("quantity_", StringType.INSTANCE)
				.addScalar("finance_end_", StringType.INSTANCE).addScalar("zxrq_", TimestampType.INSTANCE)
				.addScalar("zxrq_", TimestampType.INSTANCE).addScalar("order_type_", StringType.INSTANCE)
				.addScalar("customer_name_", StringType.INSTANCE).addScalar("vessel_name_", StringType.INSTANCE)
				.addScalar("expense_item_name_", StringType.INSTANCE);
				return null;
			}
		}, new ICallback<List<?>, List<?>>() {

			@Override
			public List<?> execute(List<?> list) {
				
				List<OrderExpense> result = new ArrayList<OrderExpense>();
				
				for (Object object : list) {
					Object[] array = (Object[]) object;
					try {
						OrderExpense oe = EntityUtils.toEntity(array[0]);
						EntityUtils.setValue(oe, "orderNo", array[1]);
						EntityUtils.setValue(oe, "voyage", array[2]);
						EntityUtils.setValue(oe, "cntNo", array[3]);
						EntityUtils.setValue(oe, "cntNo2", array[4]);
						EntityUtils.setValue(oe, "billNo", array[5]);
						EntityUtils.setValue(oe, "boxType", array[6]);
						EntityUtils.setValue(oe, "quantity", array[7]);
						EntityUtils.setValue(oe, "financeEnd", array[8]);
						EntityUtils.setValue(oe, "zxrq", array[9]);
						EntityUtils.setValue(oe, "orderDate", array[10]);
						EntityUtils.setValue(oe, "orderType", array[11]);
						EntityUtils.setValue(oe, "customerName", array[12]);
						EntityUtils.setValue(oe, "vesselName", array[13]);
						EntityUtils.setValue(oe, "expenseItemName", array[14]);
						result.add(oe);
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
				}
				return result;
			}
		}, session);
	}
	
	
	@DataProvider
	@Transactional
	public void loadBilling(Page<OrderExpense> page, Criteria criteria, String id) {
		JpaUtil.linq(Billing.class).equal("orderExpenseId", id).desc("kprq").paging(page);
	}
	
	@DataResolver
	@Transactional
	public void saveOrderExpense(List<OrderExpense> list) {
		JpaUtil.save(list, new SmartSavePolicyAdapter() {
			@Override
			public boolean beforeInsert(SaveContext context) {
				Object parent = context.getParent();
				Object entity = context.getEntity();
				if (parent instanceof OrderExpense && entity instanceof Billing) {
					((Billing) entity).setOrderExpenseId(((OrderExpense) parent).getId());
				}
				return true;
			}
		});
	}
	
	@DataResolver
	@Transactional
	public void saveBilling(List<Billing> list) {
		JpaUtil.save(list);
	}
	
	@Expose
	@Transactional
	public void deleteBilling(String ids) {
		String[] id = ids.split(",");
		List<Billing> list = JpaUtil.linq(Billing.class).in("orderExpenseId", id).list();
		if (list != null){
			JpaUtil.remove(list);
		}
	}
	
	@Expose
	@Transactional
	public void deleteBillingById(String ids) {
		String[] id = ids.split(",");
		List<Billing> list = JpaUtil.linq(Billing.class).in("id", id).list();
		if (list != null){
			JpaUtil.remove(list);
		}
	}
	
	@DataResolver
	@Transactional
	public void saveBillingLog(List<BillingLog> list) {
		JpaUtil.save(list);
	}
	
	@DataResolver
	@Transactional
	public void saveHexiaoLog(List<HexiaoLog> list) {
		JpaUtil.save(list);
	}
	
	@DataProvider
	@Transactional
	public void loadBillingLog(Page<BillingLog> page, Criteria criteria,String orderExpenseId) {
		JpaUtil.linq(BillingLog.class).equal("orderExpenseId", orderExpenseId).desc("kpDate").paging(page);
	}
	
	@DataProvider
	@Transactional
	public void loadHexiaoLog(Page<HexiaoLog> page, Criteria criteria,String orderExpenseId) {
		JpaUtil.linq(HexiaoLog.class).equal("orderExpenseId", orderExpenseId).desc("hxDate").paging(page);
	}
}
